import json
from typing import Any

from fastapi import Depends
from sqlalchemy.orm import Session

from app.db.database import get_db
from app.models.system import Users
from app.utils import security
from app.utils.file_storage import save_storage_file, get_storage_file
from app.utils.logger import logger
from app.utils.custom_response import success_response, error_response

from app.api.system.crud.user_crud import curd_user, crud_user_role
from app.api.system.schemas import users_schema
from fastapi.security import OAuth2PasswordRequestForm
from fastapi import APIRouter, File, UploadFile, Query
from fastapi import HTTPException, status


router = APIRouter()


@router.post("/login", summary="用户登录", response_model=users_schema.LoginResp, name='用户登录')
async def login_access_token(
        *,
        db: Session = Depends(get_db),
        user_info: users_schema.UsernameAuth,
) -> Any:
    """
    用户登录
    :param db:
    :param user_info:
    :return:
    """

    # # 验证用户
    user = curd_user.authenticate(db, username=user_info.username, password=user_info.password)
    if not user:
        logger.info(f"用户名或者密码错误: username{user_info.username} password:{user_info.password}")
        return error_response(message="用户名或者密码错误", code=401)
    elif not curd_user.is_active(user):
        return error_response(message="用户被禁用", code=401)

    token_dict = security.create_token(user.id)
    resp = dict()
    resp['token'] = token_dict
    # t = token_dict['access_token']
    # print(t)
    # print(security.parse_token(t))
    resp['userinfo'] = {
        'id': user.id,
        'nickname': user.nickname,
        'username': user.username,
        'avatar': get_storage_file(user.avatar),
    }
    return success_response(data=resp)


@router.post("/register", summary="注册", response_model=users_schema.UserInfo,  dependencies=[], name='注册')
async def register(
        *,
        db: Session = Depends(get_db),
        user_info: users_schema.UserRegister,
        # current_user: Users = Depends(security.verify_admin_permission),
) -> Any:
    """
    用户注册
    :param current_user:
    :param db:
    :param user_info:
    :return:
    """

    # 创建用户
    user = curd_user.create(db, obj_in=user_info)
    # print(user)
    resp = {
        'id': user.id,
        'nickname': user.nickname,
        'username': user.username,
    }
    return success_response(data=resp, message='ok')


@router.post("/token", summary="openapi 获取 token", name='openapi 获取 token')
async def login_access_token(
        *,
        db: Session = Depends(get_db),
        form_data: OAuth2PasswordRequestForm = Depends(),
) -> Any:
    """
    openapi 获取 token
    :param form_data:
    :param db:
    :param user_info:
    :return:
    """
    # # 验证用户
    user = curd_user.authenticate(db, username=form_data.username, password=form_data.password)
    if not user:
        # logger.info(f"用户名或者密码错误: username{form_data.username} password:{form_data.password}")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="用户名或者密码错误",
            headers={"WWW-Authenticate": "Bearer"},
        )
    elif not curd_user.is_active(user):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,

            detail="用户被禁用",
            headers={"WWW-Authenticate": "Bearer"},
        )
        # raise CustomException(err_desc="用户被禁用")

    token_dict = security.create_token(user.id)
    resp = dict()
    resp['token'] = token_dict
    t = token_dict['access_token']
    return {"access_token": t, "token_type": "bearer"}


@router.get("/get_userinfo", summary="获取用户信息", response_model=users_schema.RespUserInformation, name='获取用户信息')
async def get_userinfo(
    *,
    current_user: Users = Depends(security.verify_access_token),
) -> Any:

    return curd_user.get_userinfo(current_user)


@router.post("/modify_userinfo", summary="用户修改信息", response_model=users_schema.RespUserInformation, name='用户修改信息')
async def modify_userinfo(
        *,
        db: Session = Depends(get_db),
        userinfo: users_schema.ModifyUserInfor,
        current_user: Users = Depends(security.verify_access_token),
) -> Any:

    return curd_user.get_userinfo(curd_user.partial_update(db=db, user=current_user, obj_in=userinfo))


@router.post("/modify_password", summary="用户修改密码", response_model=users_schema.RespUserInformation,  dependencies=[], name='用户修改密码')
async def modify_password(
        *,
        db: Session = Depends(get_db),
        password_dict: users_schema.UpdatePassword,
        current_user: Users = Depends(security.verify_access_token),
) -> Any:

    return curd_user.get_userinfo(curd_user.password_update(db=db, user=current_user, obj_in=password_dict))


@router.post("/modify_avatar", summary="用户修改头像",  dependencies=[], name='用户修改头像')
async def modify_userinfo(
        *,
        db: Session = Depends(get_db),
        file: UploadFile = File(...),
        current_user: Users = Depends(security.verify_access_token),
) -> Any:

    path = save_storage_file(file, folder='user/avatar')
    curd_user.avatar_update(db=db, user=current_user, avatar=path)
    file_url = get_storage_file(path)
    return success_response(data=file_url)


@router.post("/refresh_token", summary="刷新token",  dependencies=[], name='刷新token')
async def refreshToken(
        *,
        req_body: users_schema.RefreshToken,
        current_user: Users = Depends(security.verify_access_token),
) -> Any:
    result, data = security.parse_token(req_body.refresh_token)
    # print(result, data)
    if result:
        data = json.loads(data['sub'])
        if data.get('type') == 'refresh':
            token_dict = security.create_token(current_user.id)
            resp = dict()
            resp['token'] = token_dict
            resp['userinfo'] = {
                'id': current_user.id,
                'nickname': current_user.nickname,
                'username': current_user.username,
                'avatar': current_user.avatar,
            }
            return success_response(data=resp)

    resp = {}
    msg = '请提交正确的refresh_token'
    return error_response(data=resp, message=msg)


# --------------------------------------------------------------------------------------------------------

@router.post("/create_user", summary="管理员创建用户", response_model=users_schema.RespUserInformation, name='管理员创建用户')
async def admin_create_user(
        *,
        db: Session = Depends(get_db),
        user_info: users_schema.UserCreate,
        current_user: Users = Depends(security.verify_admin_permission),
) -> Any:
    """
    管理员创建用户
    :param current_user:
    :param db:
    :param user_info:
    :return:
    """

    # 创建用户
    user = curd_user.create(db, obj_in=user_info)
    # print(user)
    resp = {
        'id': user.id,
        'nickname': user.nickname,
        'username': user.username,
    }
    return success_response(data=resp, message='ok')


@router.get("/get_user_list", summary="管理员获取用户列表", response_model=users_schema.RespUserInformation, name='管理员创建用户')
async def admin_create_user(
        *,
        db: Session = Depends(get_db),
        page: int = Query(1, description='页码', ge=1),
        page_size: int = Query(10, description='页面大小', le=50, ge=1),
        search_info: str = Query(None, description='搜索内容'),
        current_user: Users = Depends(security.verify_admin_permission),
) -> Any:
    """
    管理员获取用户列表
    :param search_info:
    :param page_size:
    :param page:
    :param current_user:
    :param db:
    :return:
    """

    resp = curd_user.get_user_list(db, page=page, page_size=page_size, search_info=search_info)
    return success_response(data=resp)


# -------------------------------------------------------------------------------------------------------------

@router.post("/modify_user_role", summary="添加修改用户角色", response_model=users_schema.SetUserRole, name='添加修改用户角色')
async def modify_user_role(
        *,
        db: Session = Depends(get_db),
        req_body: users_schema.SetUserRole,
        current_user: Users = Depends(security.verify_admin_permission),
) -> Any:
    crud_user_role.set_user_role(db, req_body=req_body)
    resp = {}
    return success_response(data=resp)


# -------------------------------------------------------------------------------------------------------------


# class MyThrottle(UserThrottle):
#     rate = "1/m"
#
#
# @router.post("/test/test", summary="", response_model=users_schema.SetUserRole, name='测试0')
# async def modify_user_role(
#     request: Request,
#         *,
#         db: Session = Depends(get_db),
#         # current_user: Users = Depends(security.verify_user_api_permission),
#         current_user=Depends(MyThrottle.allow_request)
# ) -> Any:
#     # print(request.headers)
#     print(request.url.path)
#     # request.app.state.redis.set("aaa", json.dumps({"a": 1, "b": 2}), 600)
#     # await websocket_manager.send_other_message("aaa", json.dumps({"name": "aaa", "age": 18}))
#
#     return success_response(data={})


# @router.post("/test/test1", summary="", response_model=users_schema.SetUserRole, name='测试1')
# async def modify_user_role(
#     request: Request,
#         *,
#         db: Session = Depends(get_db),
#         current_user: Users = Depends(security.verify_user_api_permission),
# ) -> Any:
#     from app.views.websocket_view import websocket_manager
#     await websocket_manager.handle_websocket_message(json.dumps({"name": "aaa", "age": 18}), "aaa")
#
#     return success_response(data={})
